package
{
	import flare.animate.Transitioner;
	import flare.animate.Tween;
	import flare.display.RectSprite;
	import flare.util.Colors;
	
	public class Shelf extends RectSprite
	{
		public static var SHELF_X:Number = 170;
		public static var SHELF_Y:Number = 10;
		public static var SHELF_WIDTH:Number = 700;
		public static var SHELF_HEIGHT:Number = 54;
		public static var SHELF_PADDING:Number = 7;
		
		private var onshelf:Array = new Array();
		private var lock:RectSprite;
		private var focus:RectSprite;
		
		private var newState:ShelfData = new ShelfData();
		private var oldState:ShelfData = new ShelfData();
		
		public function Shelf()
		{
			super(SHELF_X, SHELF_Y, SHELF_WIDTH, SHELF_HEIGHT);
			
			this.lineColor = Colors.rgba(0, 0, 0, 255);
        	this.lineWidth = 2.0;
        	
			lock = new RectSprite(0,1,0,SHELF_HEIGHT-3);
			lock.fillColor = 0xffaaaaaa;
			focus = new RectSprite(0,1,0,SHELF_HEIGHT-3);
			focus.fillColor = 0xffdddddd;
			this.addChild(lock);
			this.addChild(focus);
		}
		
		public function updateShelf(canvas:Canvas, notifyCanvas:Boolean = true):void
		{
			shift();
			updateFocus(lock.width);
			
			oldState = newState.copy();
			newState.clear();
			
			for each (var v:Variable in onshelf) {
				var name:String = v.getText();
				var value:String = v.getValue();
				newState.addVariable(name, value);
			}
			
			canvas.variablesChanged(oldState, newState);
		}
		
		public function currentData():ShelfData
		{
			var currentState:ShelfData = new ShelfData();
			
			for each (var v:Variable in onshelf) {
				var name:String = v.getText();
				var value:String = v.getValue();
				currentState.addVariable(name, value);
			}
			
			return currentState;
		}
		
		public function updateState():void
		{
			newState = currentData();
		}
		
		public function zoomIn(value:String):void
		{
			for each (var v:Variable in onshelf) {
				if (v.isLocked()) {
					continue;
				}
				// by the time we get here we're guaranteed v is the
				// correct attribute to set the value of
				v.setValue(value);
				var pos:Number = onshelf.indexOf(v);
				moveLock(pos);
				
				updateState();
				
				break;
			}
		}
		
		public function zoomOut():void
		{
			for (var i:Number = onshelf.length-1; i>=0; i--) {
				var v:Variable = onshelf[i];
				if (v.isLocked()) {
					clearValue(v.getText());
					updateState();
					return; // only clears the first locked variable
				}
			}
			
			updateState();
		}
		
		public function zoomTo(v:Variable, canvas:Canvas):void
		{
			var zoomLevel:Number = 0;
			for (var i:Number = onshelf.length-1; i>=0; i--) {
				var cur:Variable = onshelf[i];
				if (v.isLocked()) zoomLevel++;
				if (v == cur) break;
			}
			
			//TODO: multi-level zoom out
			
			zoomOut();
			canvas.zoomOut(false);			
		}
		
		public function setValue(text:String, value:String):void
		{
			for each (var v:Variable in onshelf) {
				if (v.getText() == text) {
					v.setValue(value);
					var pos:Number = onshelf.indexOf(v);
					moveLock(pos);
				}
			}
		}
		
		public function clearValue(text:String):void
		{
			for each (var v:Variable in onshelf) {
				if (v.getText() == text && v.isLocked()) {
					v.clearValue();
					var pos:Number = onshelf.indexOf(v);
					moveLock(pos-1);
				}
			}
		}
		
		public function getVariables():Array
		{
			return onshelf;
		}
		
		public function getVariableNames():Array
		{
			var arr:Array = new Array();
			for each (var v:Variable in onshelf) {
				arr.push(v.getText());
			}
			return arr;
		}
		
		public function getVariablePosition(v:Variable):Number
		{
			return onshelf.indexOf(v);
		}
		
		public function addVariable(v:Variable, pos:Number):void
		{
			if (pos == -1) pos = onshelf.length;
			onshelf.splice(pos,0,v);
			v.y = Shelf.SHELF_Y + Shelf.SHELF_PADDING;
		}
		
		public function removeVariableAt(pos:Number):void
		{
			onshelf.splice(pos,1);
		}
		
		public function onShelf(v:Variable):Boolean
		{
			return (getVariablePosition(v) != -1);
		}
		
		public function aboveShelf(v:Variable):Boolean
		{
			return (
				v.x + Variable.BOX_WIDTH > SHELF_X &&
				v.x < SHELF_X + SHELF_WIDTH &&
				v.y + Variable.BOX_HEIGHT > SHELF_Y &&
				v.y < SHELF_Y + SHELF_HEIGHT
			);
		}
		
		public function shift():void
		{
			var trans:Transitioner = new Transitioner(0.15);
			for (var i:Number = 0; i < onshelf.length; i++) {
				var newX:Number = SHELF_X + SHELF_PADDING + i * (Variable.BOX_WIDTH + SHELF_PADDING);
				trans.$(onshelf[i]).x = newX;
			}
			trans.play();
		}
		
		public function moveLock(pos:Number):void
		{
			var newX:Number = (pos+1) * (Variable.BOX_WIDTH + SHELF_PADDING);
			if (pos >= 0) newX += SHELF_PADDING/2;
			var newW:Number = newX - lock.x;
			new Tween(lock, 0.25, {w:newW}).play();
			updateFocus(newW);
		}
		
		private function updateFocus(newX:Number):void
		{
			var varsInFocus:Number = 0;
			for each (var v:Variable in onshelf) {
				if (v.isLocked()) continue;
				varsInFocus++;
				if (varsInFocus == 2) break;
			}
			
			var newW:Number = varsInFocus * (Variable.BOX_WIDTH + SHELF_PADDING);
			if (newX == 0 && newW != 0) newW += SHELF_PADDING/2;
			
			var trans:Transitioner = new Transitioner(0.25);
			trans.$(focus).x = newX;
			trans.$(focus).w = newW;
			trans.play();
		}
		
		public function size():Number
		{
			return onshelf.length;
		}

	}
}